#!/usr/bin/python
# -*- coding: utf-8 -*-

from jabberbot import JabberBot, botcmd
import time, os, sys, re, urllib
import Queue
import logging
import socket
import memcache

from threading import Thread
from datetime import datetime
from config import BOT_NICK, BOT, CONF, CHAT_LOG_FILE, LOG_DIR, LOG_FILE, MESSAGE_SOCKET, MESSAGE_FILE
from config import MEMCACHED_HOST, MEMCACHED_PATTERN
from cgi import escape

mc = memcache.Client([MEMCACHED_HOST], debug=0)

logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG)

class JBotSocketListener(Thread):
    def __init__(self, q):
        Thread.__init__(self)
        self.socket_file = MESSAGE_SOCKET
        self.q = q
        self.__finished = False

    def open_socket(self):
        logging.info('opening socket {0}'.format(self.socket_file))
        self.socket = socket.socket(socket.AF_UNIX) # создаём сокет домена AF_UNIX
        self.socket.bind(self.socket_file)          # привязываем его к файлу
        self.socket.settimeout(5) #timeout for socket.accept()

    def close_socket(self):
        self.socket.close()

    def exit(self):
        print "Socket listener stop!"
        self.__finished = True
        self.socket.shutdown(socket.SHUT_WR)
        self.socket.close()

    def listen(self):
        logging.info('listening socket')
        self.socket.listen(10)                       # начинаем прослушивать
        logging.info('waiting for connection')
        # conn.send('HELO')               
        while not self.__finished:
            try:
                conn, addr = self.socket.accept()           # ждём подключения
                data = conn.recv(1024)        # получаем от клиента данные
                if data:
                    logging.info('recieved {0} bytes from socket: '.format(len(data), data) )
                    print data
                    self.q.put(data)
            except socket.timeout:
                pass

        print "Socket listener stopped"

    def run(self):
        try: os.remove(MESSAGE_SOCKET)
        except: pass

        logging.info('Starting socket listener')
        self.open_socket()
        self.listen()


class WebChatBot(JabberBot):
    def __init__(self, *args, **kwargs):

        super(WebChatBot, self).__init__(*args, **kwargs)

        self.log.info("---- init ikitobot ----")
        self.nick = BOT_NICK
        self.start_time = time.time()
        self.timer = time.time()
        self.messageCounter=0

        self.messages_queue = Queue.Queue()

        self.log.info('starting socket listener thread')
        self.socket_listener = JBotSocketListener(self.messages_queue)
        self.socket_listener.start()

        self.last_message_id = None

    def send_to_conference(self, msg):
        self.send(CONF[0], msg, message_type="groupchat")

    def send_to_user(self, jid, msg):
        self.send(jid, msg, message_type="chat")

    def unknown_command(self, mess, cmd, args):
        type = mess.getType()
        jid = mess.getFrom()
        props = mess.getProperties()
        text = mess.getBody()
        username = self.get_sender_username(mess)
        # logging.info(json.dumps(mess))
        if type == "groupchat":
            self.messageCounter+=1
            self.log_conference_message(username, text)
            if username!=BOT_NICK: self.process_conf_message(username, text, mess=mess)
        if type == "chat":
            if username!=BOT_NICK: self.process_incoming_message(jid, text, mess=mess)
            pass
    
    def clear_last_message_cache(self):
        mc.set(MEMCACHED_PATTERN%self.last_message_id, None)

    def log_conference_message(self, nick, text):
        """ save message to conference log file """
        self.clear_last_message_cache()
        self.last_message_id = str(int(time.time())) + str(self.messageCounter)
        line = u"#%s %s %s> %s"%(self.last_message_id, time.strftime("%d.%m.%Y %H:%M:%S"), nick, text)
        line = line.encode('utf-8')
        logging.info('logging message from chat')
        f = open(CHAT_LOG_FILE,"a")
        f.write(line+"\n")
        f.close()

    def process_conf_message(self, nick, text, **kwargs):
        # override me
        if text and not nick==BOT_NICK:
            self.log.info(u'See groupchat message from {0}: {1}'.format(nick, text))
        pass

    def process_incoming_message(self, from_user, text, **kwargs):
        # override me
        pass
    def send_from_file(self):
        """ send text from MESSAGE_FILE to conference """
        text=u''
        lines=open(MESSAGE_FILE,'r').readlines()
        if len(lines): self.log.debug('send_from_file: read {0} lines from message file'.format(len(lines)))
        for line in lines:
            try: line=unicode(line, 'utf-8')
            except UnicodeDecodeError:
                print >> sys.stderr, "sendFromFile error: file read, but lines not encoded..."
                self.log.warning('send_from_file: line not encoded')
            if (len(line.strip('\n'))): text+=line+"\n"

        if len(text):
            self.log.info( 'got {0} bytes from message file'.format(len(text)) )
            self.send_to_conference(text)
            f=open(MESSAGE_FILE,'w')
            f.close()

    def process_task(self, msg):
        self.log.warning('original process_task called. it must be redefined!')
        self.send_to_conference(msg)

    def check_queue(self):
        """ looking for tasks in queue end send them to conference """
        if not self.messages_queue.empty():
            self.log.debug(u'got {0} tasks in messages queue'.format(self.messages_queue.qsize()) )
            while not self.messages_queue.empty():
                msg = self.messages_queue.get()
                self.messages_queue.task_done()
                self.process_task(msg)
                self.log.debug('task_done. {0} left'.format(self.messages_queue.qsize()) )

    def idle_proc(self):
        """This function will be called in the main loop."""
        if (time.time()-self.timer)>2:
            self.send_from_file()
            self.check_queue()
            self.timer=time.time()

        self._idle_ping() # Pings the server, calls on_ping_timeout() on no response.

    def shutdown(self):
        self.log.info("Shutting down socket listener. Please wait 10 seconds...")
        self.socket_listener.exit()

    def run(self):
        print "---- ikitobot start! ----"
        self.log.info("---- ikitobot start! ----")
        self.messageCounter=0
        

        self.log.info('entering to conference {0}'.format(CONF[0]))
        self.join_room(CONF[0], BOT_NICK)

        print "------ bot started ------"
        self.log.info('bot started!')

        self.send_to_conference(u'Я пришел!')
        self.send_from_file()

        self.serve_forever()

# if __name__ == '__main__':
#     ikitobot = IkitoBot(*BOT)
#     ikitobot.join_room(CONF[0], BOT_NICK)
#     ikitobot.serve_forever()


